@using ChartJs.Blazor
@using ChartJs.Blazor.Common
@using ChartJs.Blazor.Common.Enums
@using ChartJs.Blazor.Util
@using ChartJs.Blazor.BarChart
@using System.Drawing

@inject HttpClient _http
@inject IStringLocalizer<Resource> _localizer

<div class="dash-widget dash-pan">
    <div class="dash-pan-header">
        <div class="dash-pan-title me-auto">@_localizer["analytics"]</div>
        <div class="dropdown dropdown-flush">
            <a class="text-muted" type="button" id="dropdownAnalytics" data-bs-toggle="dropdown" aria-expanded="false" href="#">
                <span>@(_hideList ? _localizer["chart"] : _localizer["list"])</span> - <span>@PeriodLabel()</span>
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-chevron-down" viewBox="0 0 16 16">
                    <path fill-rule="evenodd" d="M1.646 4.646a.5.5 0 0 1 .708 0L8 10.293l5.646-5.647a.5.5 0 0 1 .708.708l-6 6a.5.5 0 0 1-.708 0l-6-6a.5.5 0 0 1 0-.708z" />
                </svg>
            </a>

            <div class="dropdown-menu dropdown-menu-end p-3" aria-labelledby="dropdownAnalytics">
                <div class="mb-1 text-muted">@_localizer["date"]:</div>
                <ul class="mb-3 list-unstyled">
                    @if (_dateOptions != null && _model != null)
                    {
                        foreach (var option in _dateOptions)
                        {
                            var cls = _model.DisplayPeriod == (AnalyticsPeriod)option.Id ? "py-1 px-2 rounded dropdown-item active" : "py-1 px-2 rounded dropdown-item";
                            <li><button type="button" class="@cls" @onclick="() => DateOptionSelect(option.Id)">@option.Title</button></li>
                        }
                    }
                </ul>
                <div class="mb-1 text-muted">@_localizer["view"]:</div>
                <div class="btn-group w-100" role="group" aria-label="Basic radio toggle button group">
                    @if (_hideList)
                    {
                        <input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" checked @onchange="() => ToggleAnalyticsView(true)">
                    }
                    else
                    {
                        <input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" @onchange="() => ToggleAnalyticsView(true)">
                    }
                    <label class="btn btn-sm btn-outline-blogifier w-50" for="btnradio1">@_localizer["chart"]</label>
                    @if (_hideGraph)
                    {
                        <input type="radio" class="btn-check" name="btnradio" id="btnradio2" autocomplete="off" checked @onchange="() => ToggleAnalyticsView(false)">
                    }
                    else
                    {
                        <input type="radio" class="btn-check" name="btnradio" id="btnradio2" autocomplete="off" @onchange="() => ToggleAnalyticsView(false)">
                    }
                    <label class="btn btn-sm btn-outline-blogifier w-50" for="btnradio2">@_localizer["list"]</label>
                </div>
            </div>

        </div>
    </div>

    <!--
        The list of posts/pages in the selected time,
        sorting by the higher visits.

        Note:
        A single visitor maybe visits 10 pages, so that's why we have Visits and Visitors.
    -->
    <ul hidden="@_hideList" class="dash-list">
        <li class="dash-list-item">
            <strong class="dash-list-title">@_localizer["title"]</strong>
            <strong class="dash-list-text">@_localizer["visits"]</strong>
        </li>
        @if (_visits != null && _visits.Count > 0)
        {
            foreach (var visit in _visits)
            {
                <li class="dash-list-item">
                    <span class="dash-list-title">@visit.Name</span>
                    <span class="dash-list-text pe-2">@visit.Value</span>
                </li>
            }
        }
    </ul>

    <!--
        Chart must show visits per day not by the title of the post.
    -->
    <div class="dash-pan-body" hidden="@_hideGraph">
        <Chart Config="_config"></Chart>
    </div>

</div>
<ToasterComponent @ref="Toaster" />

@code {
   protected ToasterComponent Toaster;
   private BarConfig _config;
   protected List<PostVisit> _visits;

   protected bool _hideGraph = false;
   protected bool _hideList = true;

   protected List<OptionItem> _dateOptions;
   protected AnalyticsModel _model;

   protected override async Task OnInitializedAsync()
   {
       _config = GetConfig();

       _dateOptions = new List<OptionItem>();
       _dateOptions.Add(new OptionItem { Id = 1, Title = _localizer["today"] });
       _dateOptions.Add(new OptionItem { Id = 2, Title = _localizer["yesterday"] });
       _dateOptions.Add(new OptionItem { Id = 3, Title = _localizer["7-days"] });
       _dateOptions.Add(new OptionItem { Id = 4, Title = _localizer["30-days"] });
       _dateOptions.Add(new OptionItem { Id = 5, Title = _localizer["90-days"] });

       await Load();
   }

   protected async Task Load()
   {
       IDataset<int> dataset = new BarDataset<int>()
       {
           Label = "Latest Post Views",
           BackgroundColor = ColorUtil.FromDrawingColor(Color.FromArgb(98, 42, 255)),
           BorderWidth = 0
       };

       _model = await _http.GetFromJsonAsync<AnalyticsModel>("api/analytics");

       if (_model == null || _model.LatestPostViews == null)
       {
           LoadData(dataset, TestData());
       }
       else
       {
           _hideList = _model.DisplayType == AnalyticsListType.Graph;
           _hideGraph = _model.DisplayType == AnalyticsListType.List;

           LoadData(dataset, _model.LatestPostViews);
       }

       if (_config.Data.Datasets.Count > 0)
       {
           _config.Data.Datasets.Clear();
       }

       _config.Data.Datasets.Add(dataset);
   }

   protected BarConfig GetConfig()
   {
       return new BarConfig
       {
           Options = new BarOptions
           {
               Responsive = true,
               Legend = new Legend
               {
                   Position = Position.Top
               }
           }
       };
   }

   protected void LoadData(IDataset<int> dataset, BarChartModel model)
   {
       _visits = new List<PostVisit>();
       var labels = model.Labels.ToList();
       var values = model.Data.ToList();

       _config.Data.Labels.Clear();

       for (int i = 0; i < labels.Count; i++)
       {
           _config.Data.Labels.Add(labels[i]);
           dataset.Add(values[i]);

           _visits.Add(new PostVisit { Name = labels[i], Value = values[i] });
       }
       _visits = _visits.OrderByDescending(v => v.Value).ToList();
   }

   protected async Task ToggleAnalyticsView(bool isGraph)
   {
       _hideGraph = await Task.FromResult(!isGraph);
       _hideList = isGraph;

       int typeId = isGraph ? 2 : 1;

       Toaster.Toast(await _http.PutAsJsonAsync<int>($"api/analytics/displayType/{typeId}", typeId));
   }

   protected async Task DateOptionSelect(int id)
   {
       Blog blog = await _http.GetFromJsonAsync<Blog>("api/blog");
       blog.AnalyticsPeriod = id;
       _model.DisplayPeriod = (AnalyticsPeriod)id;
       Toaster.Toast(await _http.PutAsJsonAsync<Blog>("api/blog", blog));
       await Load();
   }

   protected BarChartModel TestData()
   {
       return new BarChartModel()
       {
           Labels = new List<string>() { "Post One", "Post Two", "Post Three", "Post Four", "Post Five", "Post Six" },
           Data = new List<int>() { 12036, 15350, 9457, 11104, 7938, 8136 }
       };
   }

   protected string PeriodLabel()
   {
       if (_model == null)
           return "";
       return _model.DisplayPeriod.ToString();
   }
}
